home *** CD-ROM | disk | FTP | other *** search
- #! /bin/sh
- # $Header: /home/jerry/.bin/RCS/mail.sort,v 3.6 92/08/09 23:26:31 jerry mh_contrib $
- ### mail.sort - sort mail messages in place, or link to temporary folder
- ### Usage: mail.sort [folder] [-verbose] [-help] [-link [msgs]] [-c|f|o|s|t|x]"
- ##
- ## THE sortm(1) PROGRAM FROM MH 6.6 CAN SORT MAIL MESSAGES BY
- ## DATE. BUT IF YOU WANT TO GROUP ORIGINAL MESSAGES WITH THEIR
- ## REPLIES, OR SORT BY THE PERSON WHO SENT THEM, YOU CAN USE THIS
- ## SCRIPT. (THE MH 6.7 sortm IS MORE POWERFUL--AND IT DOES A LOT,
- ## BUT NOT ALL, OF WHAT mail.sort DOES.)
- ##
- ## mail.sort CAN SORT BY SUBJECT, IGNORING THE Re: SO THAT REPLIES
- ## ARE GROUPED WITH THE ORIGINAL MESSAGE. IT CAN SORT BY THE
- ## Sender:, IF THERE IS ONE-- OTHERWISE, BY THE From:. THERE ARE 6
- ## OTHER WAYS TO SORT, AS WELL.
- ##
- ## mail.sort USES scan FORMAT STRINGS TO PULL HEADER INFORMATION
- ## OUT OF EACH MESSAGE. SO, IF YOU CAN WRITE A FORMAT STRING, YOU
- ## CAN SORT BY IT. IF THERE'S A FORMAT STRING THAT YOU USE A LOT,
- ## YOU CAN ADD A NEW OPTION TO mail.sort (BY ADDING A SINGLE LINE
- ## OF CODE) THAT LETS YOU USE THAT FORMAT STRING ANY TIME, JUST BY
- ## TYPING YOUR NEW OPTION ON THE COMMAND LINE.
- ##
- ## BY DEFAULT, mail.sort SORTS MESSAGES AND PUTS THEM BACK IN THE
- ## SAME FOLDER. IT CAN ALSO LINK ALL THE MESSAGES INTO A TEMPORARY
- ## SUB-FOLDER WITHOUT CHANGING THE SOURCE FOLDER ORDER. WHEN
- ## YOU'RE DONE WITH THE SUB-FOLDER, YOU CAN REMOVE IT.
- ##
- ## THE -v OPTION WRITES VERBOSE INFO ABOUT WHAT'S HAPPENING TO stdout.
- #
- # NOTE TO HACKERS: TABSTOPS SET AT 4 IN THIS CODE
- #
- # USE AT YOUR OWN RISK. SEEMS TO WORK, BUT IT'S YOUR RESPONSIBILITY!
- # PLEASE TELL ME ABOUT BUGS AND FIXES: Jerry Peek, jerry@ora.com
-
- umask 77 # PROTECT TEMPORARY FILE
- folopts="-nolist -nototal" # OVERRIDE MH PROFILE
- mh=/usr/local/mh # WHERE MH COMMANDS LIVE
- myname="`basename $0`" # THIS PROGRAM'S NAME
- scanopts="-width 200 -noclear -noheader -noreverse" # OVERRIDE MH PROFILE
- stat=1 # DEFAULT EXIT STATUS; RESET TO 0 BEFORE NORMAL exit
- subfol=MAILSORT$$ # TEMPORARY SUB-FOLDER
- temp=/tmp/MSORT$$
- usage="Usage: $myname [folder] [-verbose] [-help] [-link [msgs]] [-c|f|o|s|t|x]"
-
- # trapS COME LATER... SEE BELOW.
-
- what=/bin/mv # DEFAULT IF NO -link
- for arg
- do
- case "$arg" in
- [+@]*) folder="$arg" ;;
- -h*) echo "$usage
-
- Replaces messages in same folder unless you use -link,
- when messages are linked into a sorted sub-folder.
-
- Sorts by Subject with Re:'s stripped,
- unless you use one of the following:
- -f[rom]
- -s[ender]
- -o[rigin] (Sender, otherwise From)
- -t[o]
- -c[c]
- -r[eply-to]
- -x (exact Subject, including Re:'s)
-
- $myname, \$Revision: 3.6 $ \$Date: 92/08/09 23:26:31 $"
- stat=0
- exit
- ;;
- -l*) what=/bin/ln ;;
- -v*) vflag=y ;;
- -*) # SET COMPONENT TO SORT ON:
- case "$how" in
- ?*) echo "$myname: '$arg'? Only one of -c, -f, -o, -s, -t, -x." 1>&2
- exit
- ;;
- esac
- # NO DATE SORT HERE BECAUSE sortm DOES THAT, AND FASTER...
- case "$arg" in
- -f*) how='%(mbox{from})' ;; # FROM (mbox)
- -s*) how='%(mbox{sender})' ;; # SENDER (mbox)
- -t*) how='%(mbox{to})' ;; # TO (IGNORE MUTIPLE ADDRESSES)
- -c*) how='%(mbox{cc})' ;; # CC (IGNORE MUTIPLE ADDRESSES)
- -r*) how='%(mbox{reply-to})' ;; # REPLY-TO (mbox)
- -x*) how='%{subject})' ;; # EXACT SUBJECT (INCLUDE Re:)
- -o*) # SORT BY Sender, IF THERE IS ONE, OTHERWISE BY From:
- how='%<{sender}%(mbox{sender})%|%(mbox{from})%>'
- ;;
- *) echo "$usage
- (invalid switch '$arg')" 1>&2
- exit
- ;;
- esac
- ;;
- *) # ONLY ALLOW MESSAGE ARGUMENTS IF LINKING; CAN RUIN FOLDER OTHERWISE:
- case "$what" in
- *ln) msgargs="$msgargs $arg" ;;
- *) echo "$usage
- ('$arg'? No message numbers unless using -link.)" 1>&2
- exit 1
- ;;
- esac
- ;;
- esac
- done
-
- origfol="`$mh/folder $folopts $folder -fast`"
- cd `$mh/mhpath +$origfol` || exit
-
- # SET trapS THAT TELL USER HOW TO RECOVER WHEN stat != 1:
- trap 'echo "$myname: Interrupted." 1>&2' 1 2 15
- case "$what" in
- *ln) # SPECIAL MESSAGE FOR LINKING:
- trap 'case "$stat" in 1) echo "$myname: You should run:
- rmf +$origfol/$subfol" 1>&2;; esac;
- rm -f $temp; exit $stat' 0
- ;;
- *) trap 'case "$stat" in 1) echo "$myname: Recover with:
- folder +$origfol/$subfol
- refile all @..
- folder (be sure +$origfol/$subfol is empty)
- rmf (remove +$origfol/$subfol)" 1>&2;; esac' 0
- ;;
- esac
-
- mkdir $subfol || exit
-
- exec 3>&2 # SAVE ORIGINAL stderr; WE RESTORE IT LATER
- exec 2>$temp # THROW stderr MESSAGES INTO $temp; TEST AT END OF THIS MESS
-
- case "$vflag" in
- y) echo "$myname: sorting messages to temporary folder..." ;;
- esac
- # START LONG PIPELINE TO GET LIST OF MESSAGES, WITH OLD AND NEW NUMBERS.
- # SPIT MESSAGE NUMBERS AND TEXT FIELD TO STANDARD OUTPUT OF case.
- case "$how" in
- "") # SORT BY SUBJECT (DEFAULT); STRIP OFF "Re:", "RE:", "Re: Re:", ETC:
- $mh/scan $scanopts -format '%(msg)#%{subject}' $msgargs |
- sed -n '
- /^[1-9][0-9]*#[Rr][Ee]:/ {
- :rezap
- s/^\([1-9][0-9]*#\)[Rr][Ee]: */\1/
- /^[1-9][0-9]*#[Rr][Ee]:/b rezap
- }
- p'
- ;;
- *) # SORT BY WHATEVER ELSE (FORMAT STRING IS IN $how):
- $mh/scan $scanopts -format "%(msg)#$how" $msgargs
- ;;
- esac |
- sort -t\# +1 | # SORT BY TEXT FIELD
- awk '{ kut = index($0, "#") # ADD NEW MESSAGE NUMBERS, REMOVE "#"
- print NR, substr($0, 1, kut-1), substr($0, kut+1) }' |
- while read new old text
- do
- # MOVE OR LINK MESSAGES INTO SUB-FOLDER, ONE BY ONE.
- #
- # IF MESSAGE WAS UNREADABLE, scan PRINTED A LINE (TO STANDARD
- # OUTPUT!) LIKE THIS, WITH LEADING BLANKS UNLESS msgnum > 999:
- # <msgnum> unreadable
- # WE GET THAT WITH A LINE NUMBER IN FRONT FROM awk...
- # IF THERE ARE LEADING BLANKS, SOME BOURNE SHELLS WILL COPY ALL
- # THIS STUFF INTO $text, AND LEAVE BOTH $new AND $old
- # EMPTY. TRY TO CATCH BOTH CASES:
- case "$new" in
- "") echo "$myname: message $new $old $text" 1>&2; break ;;
- esac
- case "$text" in
- unreadable) echo "$myname: can't read msg '$old'???" 1>&2; break ;;
- esac
- # USE UNIX COMMANDS; AVOID ALL THE OVERHEAD THAT refile WOULD ADD:
- if $what $old $subfol/$new
- then
- case "$vflag" in
- y) echo "$myname: old #$old --> new #$new ($text)" ;;
- esac
- else
- echo "$myname: '$what $old $subfol/$new' failed." 1>&2
- break
- fi
- done
- exec 2>&- # CLOSE TEMPORARY stderr
- exec 2>&3 # RESTORE ORIGINAL stderr
-
- # IF THERE WERE ANY ERRORS IN THE MESS ABOVE, SHOW THEM AND EXIT:
- if test -s $temp
- then
- echo "$myname: quitting:" 1>&2
- cat $temp 1>&2
- exit
- fi
-
- set -e # exit IF ANY ERROR FROM NOW ON
-
- case "$what" in
- *ln)
- case "$vflag" in
- y) $mh/folder @$subfol
- echo "$myname: done."
- echo "When you're done with this sub-folder, type 'rmf' to remove it."
- ;;
- *) $mh/folder -fast @$subfol >/dev/null ;;
- esac
- ;;
- *)
- # cd TO SUB-FOLDER AVOIDS LONG PATHNAMES (& COMMAND LINE OVERFLOW):
- cd $subfol
- case "$vflag" in
- y) echo "$myname: moving messages back to original folder..." ;;
- esac
- /bin/mv * ..
- cd ..
- /bin/rmdir $subfol
- ;;
- esac
- stat=0
- exit
-